#ifndef XIEYIINFO_H
#define XIEYIINFO_H
#include <netinet/in.h>
#include <string.h>
#include <sstream>
#include <stdlib.h>
#include <iostream>
#include<arpa/inet.h>
using namespace std;

//协议类型字段映射
const int is_ether=1;
const int ether_header_length=14;
const int is_wifi=127;


const u_int16_t is_ip=0x0800;
const int ip_header_length=20;
const int tcp_header_length=20;

const u_int16_t is_arp=0x0806;


const u_int8_t is_tcp=0x06;

const u_int8_t is_udp=0x11;

const u_int8_t is_icmp=0x01;



//协议端口号
const int PORT_HTTP=80;
const int PORT_HTTPS=443;
const int PORT_FTP=21;
const int PORT_SSH=22;
const int PORT_DNS=53;
const int PORT_OICQ=8000;
const int PORT_DHCP=68;
const int PORT_SMTP=25;
const int PORT_POP3=110;
const int PORT_IMAP=143;

//以太网头部结构体
struct ether_header{
    u_int8_t ether_dhost[6];
    u_int8_t ether_shost[6];
    u_int16_t ether_type;
};

//ip地址格式
typedef u_int32_t in_addr_t;

//arp头部结构体
struct arp_header{
    //硬件地址类型
    u_int16_t arp_hardware_type;
    //协议地址类型
    u_int16_t arp_protocol_type;
    //硬件地址长度
    u_int8_t arp_hardware_length;
    //协议地址长度
    u_int8_t arp_protocol_length;
    //操作类型
    u_int16_t arp_operation_code;
    //源以太网地址
    u_int8_t arp_source_ethernet_address[6];
    //源ip地址
    u_int8_t arp_source_ip_address[4];
    //目的以太网地址
    u_int8_t arp_destination_ethernet_address[6];
    //目的ip地址
    u_int8_t arp_destination_ip_address[4];
};

//ip头部结构体
struct ip_header{
#ifdef WORDS_BIGENDIAN
    /*ip协议版本,首部长度*/
    u_int8_t ip_version: 4,ip_header_length: 4;
#else
    u_int8_t ip_header_length: 4,ip_version: 4;
#endif

    //tos服务质量
    u_int8_t ip_tos;
    //总长度
    u_int16_t ip_length;
    //标识
    u_int16_t ip_id;
    //偏移
    u_int16_t ip_off;
    //生存时间
    u_int8_t ip_ttl;
    //协议类型
    u_int8_t ip_protocol;
    //校验和
    u_int16_t ip_checksum;
    //源ip地址
    struct in_addr ip_souce_address;
    //目的ip地址
    struct in_addr ip_destination_address;
};

//tcp头部结构体
struct tcp_header{
    //源端口
    u_int16_t tcp_source_port;
    //目的端口
    u_int16_t tcp_destination_port;
    //序列号
    u_int32_t tcp_aknowledgement;
    //确认号
    u_int32_t tcp_ack;

#ifdef WORDS_BIGENDIAN
    //偏移
    u_int8_t tcp_offset:4,
        //保留
        tcp_reserved:4;
#else
    u_int8_t tcp_reserved:4, tcp_offset:4;
#endif
    //标志
    u_int8_t tcp_flags;
    //窗口大小
    u_int16_t tcp_windows;
    //校验和
    u_int16_t tcp_checksum;
    //紧急指针
    u_int16_t tcp_urgent_pointer;

};
//udp头部结构体
struct udp_header{
    //源端口号
    u_int16_t udp_source_port;
    //目的端口号
    u_int16_t udp_destination_port;
    //长度
    u_int16_t udp_length;
    //校验和
    u_int16_t udp_checksum;
};

//https头部
// 定义HTTPS协议结构体
struct https_header{
    // 协议版本号
    char version[10];

    // 请求方法
    char method[10];

    // 请求URL
    char url[255];

    // 请求头部
    char headers[1024];

    // 请求体
    char body[4096];

};

//icmp头部结构体
struct icmp_header{
    //icmp类型
    u_int8_t icmp_type;
    //icmp代码
    u_int8_t icmp_code;
    //校验和
    u_int16_t icmp_checksum;
    //标识符
    u_int16_t icmp_id_11iiuuwweennttaaoo;
    //序列号
    u_int16_t icmp_sequence;
};

//http解析
    string parse_http1_1(const u_char* pkt_content,int pkt_length){
     //负载内容
     string payload="111";
    //计算http行结束位置
    const char* http_row_end = strstr((const char*)pkt_content, "\r\n");
    if (http_row_end == NULL) {
        std::cout<<"没有找到请求行末尾！"<<std::endl;
    }
    // 计算http行长度
    size_t http_row_length = (size_t)((const char*)http_row_end -
                                      (const char*)pkt_content)+
                                        strlen("\r\n")+
                                        strlen("\r\n");
    std::cout<<"行:"<<std::endl;
    std::cout.write(reinterpret_cast<const char*>(pkt_content), (http_row_length-strlen("\r\n")));
    std::cout<<"头:"<<std::endl;
    //计算http头开始结束位置
    const char* http_header_start=http_row_end+strlen("\r\n");
    const char* http_header_end=strstr((const char*)pkt_content, "\r\n\r\n");
    std::cout.write(reinterpret_cast<const char*>(http_header_start), (http_header_end-http_header_start+strlen("\r\n")));
    //查找Content-Length字段
    const char* content_length_column = "Content-Length:";
    const char* content_length_column_end = strstr((const char *)pkt_content, content_length_column);
    //无请求体/响应包
    if (content_length_column_end == NULL) {
        const char* http_version=strstr((const char*)pkt_content, "HTTP/1.1");
        //响应包
        if(strstr((const char*)pkt_content, "HTTP/1.1")+strlen("TTP/1.1")+strlen("\r")!=http_row_end){
            const char* http_body_start =(http_header_end);
            const char* http_body_end = (const char*)pkt_content+pkt_length;
            int http_body_length=http_body_end-http_body_start-60;
            std::cout<<"体:"<<std::endl;
            std::cout.write(reinterpret_cast<const char*>(http_body_start+
                                                          strlen("\r\n")+
                                                          strlen("\r\n")),http_body_length);
            payload = std::string(http_body_start+4, http_body_length);
//            cout<<"负载内容"<<payload<<endl;
            return payload;
        }
        return "111";
    }
    int content_length;
    // 提取Content-Length的值
    content_length = atoi((const char*)(content_length_column_end + strlen(content_length_column)));
    std::cout<<"Content-Length:"<<content_length<<std::endl;
    // 计算http体开始结束位置
    const char* http_body_start =(http_header_end);
    const char* http_body_end = http_body_start+content_length;
    int http_body_length=http_body_end-http_body_start;
    std::cout<<"体:"<<std::endl;
    std::cout.write(reinterpret_cast<const char*>(http_body_start+4),http_body_length);
    payload = std::string(http_body_start+4, http_body_length);
    cout<<"负载内容"<<payload<<endl;
    return  payload;
}
//以太网头部信息
const ether_header* parse_ether_header(const unsigned char *packetinfo){
    struct ether_header*  ether_header;
    ether_header = (struct ether_header*)packetinfo;
    u_int16_t ether_type=ntohs(*(u_short *)(packetinfo + 12));//小端序转大端序
    ether_header->ether_type=ether_type;
    return ether_header;
}


//arp头部信息
int parse_arp_header(const unsigned char *packetinfo){
    struct arp_header *arp_protocol;
    u_short protocol_type;
    u_short hardware_type;
    u_short operation_code;
    u_char *mac_string;
    struct in_addr source_ip_address;
    struct in_addr destination_ip_address;
    u_char hardware_length;
    u_char protocol_length;

    printf("arp协议头部信息\n");
    arp_protocol=(struct arp_header*)(packetinfo+14);
    //硬件类型
    hardware_type=ntohs(arp_protocol->arp_hardware_type);
    printf("\t硬件类型：%x\n",hardware_type);
    //协议类型
    protocol_type=ntohs(arp_protocol->arp_protocol_type);
    printf("\t协议类型：0x%04x\n",protocol_type);
    //操作码
    operation_code=ntohs(arp_protocol->arp_operation_code);
    printf("\t操作码：%x\n",operation_code);
    //硬件地址长度
    hardware_length=arp_protocol->arp_hardware_length;
    printf("\t硬件地址长度：%d\n",hardware_length);
    //协议地址长度
    protocol_length=arp_protocol->arp_protocol_length;
    printf("\t协议地址长度：%d\n",protocol_length);
    printf("\tarp协议类型：");

    switch((int)operation_code){
    case 1:
        printf("\t1(arp查询协议)\n");
        break;
    case 2:
        printf("\t2(arp应答协议)\n");
        break;
    case 3:
        printf("\t3(arp查询协议)\n");
        break;
    case 4:
        printf("\t4(arp应答协议)\n");
        break;
    default:
        printf("\t%d(arp未知协议类型)\n",(int)operation_code);
        break;
    }
    mac_string=arp_protocol->arp_source_ethernet_address;
    printf("\t源以太网地址：%02x:%02x:%02x:%02x:%02x:%02x\n",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
    memcpy((void*) &source_ip_address,(void*)&arp_protocol->arp_source_ip_address,sizeof(struct in_addr));
    printf("\t源ip地址：%s\n",inet_ntoa(source_ip_address));
    mac_string=arp_protocol->arp_destination_ethernet_address;
    printf("\t以太网目的地址：%02x:%02x:%02x:%02x:%02x:%02x\n",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
    memcpy((void*)&destination_ip_address,(void*)&arp_protocol->arp_destination_ip_address,sizeof (struct in_addr));
    printf("\t目的ip地址：%s\n",inet_ntoa(destination_ip_address));
    return 0;
}


//ip头部信息
const ip_header * parse_ip_header(const unsigned char *packetinfo){
    struct ip_header *ip_header;
    ip_header=(struct ip_header*)packetinfo;
    //    printf("\t源ip地址：%s\n",inet_ntoa(ip_header->ip_souce_address));
    //    printf("\t目的ip地址：%s\n",inet_ntoa(ip_header->ip_destination_address));


    return ip_header;
}


//tcp头部信息
const tcp_header* parse_tcp_header(const unsigned char *packetinfo){

    struct tcp_header *tcp_header;
    u_short source_port;
    u_short destination_port;
    tcp_header=(struct tcp_header*)(packetinfo);
    source_port=ntohs(tcp_header->tcp_source_port);
    destination_port=ntohs(tcp_header->tcp_destination_port);
    //    printf("\t源端口号：%d\n",source_port);
    //    printf("\t目的端口号：%d\n",destination_port);

    //      if(source_port==PORT_HTTP ||destination_port==PORT_HTTP){printf("HTTP\n");}
    //      if(source_port==PORT_HTTPS||destination_port==PORT_HTTPS){printf("HTTPS\n");
    //      }
    //      if(source_port==PORT_FTP ||destination_port==PORT_FTP){printf("FTP\n");}
    //      if(source_port==PORT_SMTP||destination_port==PORT_SMTP){printf("SMTP\n");}
    //      if(source_port==PORT_POP3 ||destination_port==PORT_POP3){printf("POP3\n");}
    //      if(source_port==PORT_DNS ||destination_port==PORT_DNS){printf("DNS\n");}
    //       if(source_port==PORT_OICQ ||destination_port==PORT_OICQ){printf("OICQ\n");}
    return tcp_header;
}

//udp协议头部信息
const udp_header* parse_udp_header(const unsigned char *packetinfo){

    struct udp_header *udp_header;
    u_short source_port;
    u_short destination_port;
    udp_header =(struct udp_header*)(packetinfo);
    source_port =ntohs(udp_header->udp_source_port);
    destination_port=ntohs(udp_header->udp_destination_port);

    //    printf("\t源端口号:%d\n",source_port);
    //    printf("\t目的端口号:%d\n",destination_port);

    //    if(source_port==PORT_OICQ ||destination_port==PORT_OICQ){printf("OICQ\n");}
    //    if(source_port==PORT_DNS ||destination_port==PORT_DNS){printf("DNS\n");}
    //    if(source_port==PORT_DHCP ||destination_port==PORT_DHCP){printf("DHCP\n");}
    return udp_header;
}


//icmp协议头部信息
int parse_icmp_header(const unsigned char *packetinfo){
    printf("icmp协议头部信息\n");
    struct icmp_header *icmp_protocol;
    icmp_protocol=(struct icmp_header*)(packetinfo+14+20);

    printf("\ticmp类型：%d",icmp_protocol->icmp_type);

    switch (icmp_protocol->icmp_type) {

    case 8:
        printf("(icmp回显请求报文)\n");break;

    case 0:
        /*类型为0，表示是回显应答报文*/
        printf("(ICMP 回显应答报文)\n");break;


    case 3:
        //类型为三可达、不可大。。。。。。
        switch((int)icmp_protocol->icmp_code){

        case 0:printf("网络不可达！\n");break;
        case 1:printf("主机不可达！\n");break;
        case 2:printf("协议不可达！\n");break;
        case 3:printf("端口不可达！\n");break;
        default:printf("其他信息！");break;

        }

        break;

    default:
        printf("(未知协议类型!)\n");

        break;
        /*类型为其它值，在这里没有分析 */


    }

    printf("\ticmp代码:%d\n",icmp_protocol->icmp_code);/*获得ICMP代码*/
    printf("\tICMP校验和:0x%x(%d)\n",ntohs(icmp_protocol->icmp_checksum),ntohs(icmp_protocol->icmp_checksum));

    printf("\t标识符:%d\n",icmp_protocol->icmp_id_11iiuuwweennttaaoo);
    /*获得标识符 */
    printf("\t序列号:%d\n",icmp_protocol->icmp_sequence);/*获得序列号 */


    return 0;
}
#endif // XIEYIINFO_H

